package river_city_ransom.implementations;

import java.util.ArrayList;
import java.util.List;

import exceptions.ComposantError;
import river_city_ransom.services.Equipable;
import river_city_ransom.services.Gangster;
import river_city_ransom.services.GestionCombat;
import river_city_ransom.services.Objet;
import river_city_ransom.services.Personnage;
import river_city_ransom.services.PersonnageJouable;
import river_city_ransom.services.Terrain;
import river_city_ransom.types.BlocType;
import river_city_ransom.types.Commande;
import tools.Toolbox;

public class GestionCombat_I implements GestionCombat{
	private Terrain terrain;
	private PersonnageJouable alex;
	private PersonnageJouable ryan;
	private Gangster slick;
	private List<Gangster> gangsters;
	private boolean estPret;
	private Commande commandeAlex;
	private Commande commandeRyan;
	private Commande commandesEnnemis;

	public GestionCombat_I(Terrain t){
		this.terrain = t;
	}

	@Override
	public Terrain terrain() {
		return terrain;
	}

	@Override
	public PersonnageJouable alex() {
		return alex;
	}

	@Override
	public PersonnageJouable ryan() {
		return ryan;
	}

	@Override
	public Gangster slick() {
		return slick;
	}

	@Override
	public List<Gangster> gangsters() {
		return gangsters;
	}

	@Override
	public boolean estPret() {
		return estPret;
	}

	@Override
	public Commande commandeAlex() {
		return commandeAlex;
	}

	@Override
	public Commande commandeRyan() {
		return commandeRyan;
	}

	@Override
	public boolean collision(Equipable equipable1, Equipable equipable2)
			throws ComposantError {
		if( (equipable1.dimensions().largeur() + equipable2.dimensions().largeur())/2 <= (equipable1.position().x() - equipable2.position().x())
				|| (equipable1.dimensions().profondeur() + equipable2.dimensions().profondeur())/2 <= (equipable1.position().y() - equipable2.position().y())
				|| (equipable1.dimensions().hauteur() + equipable2.dimensions().hauteur())/2 <= (equipable1.position().z() - equipable2.position().z())
				){
			return true;
		}
		return false;
	}

	@Override
	public Objet collisionObjetLance(Personnage personnage, List<Objet> objets)
			throws ComposantError {
		for(int i = 0; i < objets.size() ; i++){
			if(collision(personnage, objets.get(i)) && objets.get(i).estJete() != 0){
				return  objets.get(i);
			}
		}
		return null;
	}

	@Override
	public Objet collisionObjetRamasse(Personnage personnage, List<Objet> objets)
			throws ComposantError {
		for(int i = 0; i < objets.size() ; i++){
			if(collision(personnage, objets.get(i)) && objets.get(i).estJete() == 0){
				return  objets.get(i);
			}
		}
		return null;
	}

	@Override
	public Personnage estFrappe(Personnage personnage) throws ComposantError {
		if(personnage.nom() == "Alex" || personnage.nom() == "Ryan"){
			if(commandesEnnemis() == Commande.FRAPPE){
				for(int i =0 ; i < gangsters().size() ; i++){
					if(collision(personnage, gangsters().get(i))){
						return gangsters().get(i);
					}
				}
				if(collision(personnage, slick())){
					return slick();
				}
			}
		}else{
			if(collision(personnage, alex())){
				return alex();
			}
			if(collision(personnage, ryan())){
				return ryan();
			}
		}
		return null;
	}

	@Override
	public Personnage estPorte(Personnage personnage) throws ComposantError {
		if(personnage.nom() == "Alex" || personnage.nom() == "Ryan"){
			for(int i =0 ; i < gangsters().size() ; i++){
				if(gangsters().get(i).choseEquipee() != null){
					if(gangsters().get(i).choseEquipee().equals(personnage)){
						return gangsters().get(i);
					}
				}
			}
			if(slick().choseEquipee() != null){
				if(slick().choseEquipee().equals(personnage)){
					return slick();
				}
			}
		}else{
			if(alex().choseEquipee() != null){
				if(alex().choseEquipee().equals(personnage)){
					return alex();
				}
			}
			if(ryan().choseEquipee() != null){
				if(ryan().choseEquipee().equals(personnage)){
					return ryan();
				}
			}
		}
		return null;
	}

	@Override
	public Commande commandesEnnemis() {
		return commandesEnnemis;
	}

	@Override
	public void init(Terrain t) throws ComposantError {
		terrain = t;
		commandeAlex = null;
		commandeRyan = null;
		commandesEnnemis = null;
		alex = new PersonnageJouable_I("Alex", new Dimensions_I(10,  50,  10), 15, 100);
		ryan = new PersonnageJouable_I("Ryan", new Dimensions_I(10,  50,  10), 15, 100);
		slick = new Gangster_I("Slick", new Dimensions_I(10,  50,  10), 15, 100);
		gangsters = new ArrayList<Gangster>();
		gangsters.add(new Gangster_I("GenericDudes", new Dimensions_I(10,  50,  10), 15, 100));
		gangsters.add(new Gangster_I("HomeBoys", new Dimensions_I(10,  50,  10), 15, 100));
		gangsters.add(new Gangster_I("Squids", new Dimensions_I(10,  50,  10), 15, 100));
		gangsters.add(new Gangster_I("Squids2", new Dimensions_I(10,  50,  10), 15, 100));
		estPret = false;


	}

	@Override
	public void gerer(Commande commande1, Commande commande2)
			throws ComposantError {

		commandeAlex = commande1;
		commandeRyan = commande2;
		int rnd = (int) Math.random() * 7;

		if(rnd == 0){
			commandesEnnemis = Commande.BAS;
		}
		if(rnd == 1){
			commandesEnnemis = Commande.HAUT;
		}
		if(rnd == 2){
			commandesEnnemis = Commande.GAUCHE;
		}
		if(rnd == 3){
			commandesEnnemis = Commande.DROITE;
		}
		if(rnd == 4){
			commandesEnnemis = Commande.FRAPPE;
		}
		if(rnd == 5){
			commandesEnnemis = Commande.RAMASSER;
		}
		if(rnd == 6){
			commandesEnnemis = Commande.JETER;
		}
		gererCommande(alex, commande1);
		gererCommande(ryan, commande2);
		gererCommande(slick, commandesEnnemis());
		for (int i = 0; i < gangsters().size(); i++) {
			gererCommande(gangsters().get(i), commandesEnnemis());
		}
	}

	@Override
	public void avantPasJeu() throws ComposantError {
		estPret = true;

		if(terrain().bloc(alex().position()).type() == BlocType.FOSSE){
			terrain().delBloc(terrain().bloc(alex().position()));
			terrain().setBloc(new Bloc_I(BlocType.VIDE, alex().position()));
		}
		if(terrain().bloc(ryan().position()).type() == BlocType.FOSSE){
			terrain().delBloc(terrain().bloc(ryan().position()));
			terrain().setBloc(new Bloc_I(BlocType.VIDE, ryan().position()));
		}
	}

	@Override
	public void gererCommande(Personnage personnage, Commande commande)
			throws ComposantError {
		if(Toolbox.equals(personnage.position(), terrain().bloc(personnage.position()).position())){
			personnage.retirerPointsDeVie(personnage.maxPointsDeVie());
		}else if(estFrappe(personnage) == null && personnage.estGele() != 0 && commande != null){
			
			
		}else if( Commande.GAUCHE == commande && estFrappe(personnage) == null && personnage.estGele() == 0){
			personnage.deplacer(new Position_I(Math.max(personnage.position().x() -1,0), personnage.position().y(), personnage.position().z()));
			
		}else if( Commande.DROITE == commande && estFrappe(personnage) == null && personnage.estGele() == 0){
			personnage.deplacer(new Position_I(Math.min(personnage.position().x() +1, terrain().dimensions().largeur()), personnage.position().y(), personnage.position().z()));
			
		}else if( Commande.HAUT == commande && estFrappe(personnage) == null && personnage.estGele() == 0){
			personnage.deplacer(new Position_I(personnage.position().x(), Math.min(personnage.position().y()+1,terrain().dimensions().profondeur()), personnage.position().z()));
			
		}else if( Commande.BAS == commande && estFrappe(personnage) == null && personnage.estGele() == 0){
			personnage.deplacer(new Position_I(personnage.position().x(), Math.max(personnage.position().y() -1,0), personnage.position().z()));
			
		}else if(estPorte(personnage) != null){
			personnage.deplacer(estPorte(personnage).position());
			
		}else if(estFrappe(personnage) != null){
			personnage.retirerPointsDeVie(estFrappe(personnage).force());
			personnage.geler(5);
		}else if( collisionObjetLance(personnage, terrain().objets()) != null){
			personnage.retirerPointsDeVie(collisionObjetLance(personnage, terrain().objets()).bonusDeForce());
			personnage.geler(5);
		}else if(commande == Commande.FRAPPE && personnage.estGele() == 0){
			personnage.geler(5);
		}else{
			personnage.degeler();
		}

	}

}
